<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title></title>

    <script type="text/javascript" src="../dist/vis.js"></script>
    <link href="../dist/vis.css" rel="stylesheet" type="text/css" />

    <style type="text/css">
      #mynetwork {
        width: 600px;
        height: 400px;
        border: 1px solid lightgray;
      }
    </style>
  </head>

  <body>
    <div id="mynetwork"></div>

    <script>
      var network = null;
      // create an array with nodes
      var nodes = new vis.DataSet([
        { id: 1, label: "Node 1", cid: 1 },
        { id: 2, label: "Node 2", cid: 1 },
        { id: 3, label: "Node 3" },
        { id: 4, label: "Node 4" },
        { id: 5, label: "Node 5" },
      ]);

      // create an array with edges
      var edges = new vis.DataSet([
        { id: "e1", from: 1, to: 3, label: "hi" },
        { from: 1, to: 2 },
        { from: 2, to: 4 },
        { from: 2, to: 5 },
      ]);

      var data = {
        nodes: nodes,
        edges: edges,
      };
      var container = document.getElementById("mynetwork");

      function drawQuick() {
        draw({ physics: { stabilization: false } });
      }

      function draw(options) {
        try {
          // clean
          if (network !== null) {
            network.destroy();
            network = null;
          }
          network = new vis.Network(container, data, options);
        } catch (err) {
          console.log("err");
        }
      }

      function clusterByCid() {
        drawQuick();
        var clusterOptionsByData = {
          joinCondition: function (childOptions) {
            return childOptions.cid == 1;
          },
          clusterNodeProperties: {
            id: "cidCluster",
            borderWidth: 3,
            shape: "database",
          },
        };
        network.cluster(clusterOptionsByData);
      }

      function clusterByConnection() {
        drawQuick();
        network.clusterByConnection(1);
      }
      function clusterByHubsize() {
        drawQuick();
        var clusterOptionsByData = {
          processProperties: function (clusterOptions, childNodes) {
            clusterOptions.label = "[" + childNodes.length + "]";
            return clusterOptions;
          },
          clusterNodeProperties: {
            borderWidth: 3,
            shape: "box",
            font: { size: 30 },
          },
        };
        network.clusterByHubsize(undefined, clusterOptionsByData);
      }

      function checkMethods() {
        var methods = [
          { name: "setSize", arguments: [200, 300] },
          { name: "canvasToDOM", arguments: [{ x: 10, y: 20 }] },
          { name: "DOMtoCanvas", arguments: [{ x: 10, y: 20 }] },
          { name: "findNode", arguments: [1] },
          { name: "isCluster", arguments: [1] },
          { name: "cluster", arguments: null, func: clusterByCid },
          { name: "findNode", arguments: [1] },
          { name: "isCluster", arguments: ["cidCluster"] },
          { name: "getNodesInCluster", arguments: ["cidCluster"] },
          { name: "openCluster", arguments: ["cidCluster"] },
          {
            name: "clusterByConnection",
            arguments: null,
            func: clusterByConnection,
          },
          { name: "clusterByHubsize", arguments: null, func: clusterByHubsize },
          { name: "clusterOutliers", arguments: null, funcFirst: drawQuick },
          { name: "getSeed", arguments: null, funcFirst: drawQuick },
          { name: "enableEditMode", arguments: null },
          { name: "disableEditMode", arguments: null },
          { name: "addNodeMode", arguments: null },
          { name: "disableEditMode", arguments: null },
          {
            name: "editNode",
            arguments: null,
            funcFirst: function () {
              network.setOptions({
                manipulation: {
                  editNode: function (data, callback) {
                    callback(data);
                  },
                },
              });
            },
          },
          { name: "disableEditMode", arguments: null },
          { name: "addEdgeMode", arguments: null },
          { name: "disableEditMode", arguments: null },
          { name: "editEdgeMode", arguments: null },
          { name: "disableEditMode", arguments: null },
          { name: "selectNodes", arguments: [[5], true] },
          { name: "deleteSelected", arguments: null, funcFirst: drawQuick },
          { name: "disableEditMode", arguments: null },
          { name: "getPositions", arguments: [[1]] },
          { name: "storePositions", arguments: null, funcFirst: drawQuick },
          { name: "getBoundingBox", arguments: [1] },
          { name: "getConnectedNodes", arguments: [1] },
          { name: "getConnectedEdges", arguments: [1] },
          { name: "startSimulation", arguments: null },
          { name: "stopSimulation", arguments: null },
          { name: "stabilize", arguments: null },
          { name: "getSelection", arguments: null },
          { name: "getSelectedNodes", arguments: null },
          { name: "getSelectedEdges", arguments: null },
          { name: "getNodeAt", arguments: [{ x: 10, y: 20 }] },
          { name: "getEdgeAt", arguments: [{ x: 10, y: 20 }] },
          { name: "selectNodes", arguments: [[1], false] },
          { name: "selectEdges", arguments: [["e1"]] },
          { name: "unselectAll", arguments: null },
          { name: "redraw", arguments: null },
          { name: "getScale", arguments: null },
          { name: "getViewPosition", arguments: null },
          { name: "fit", arguments: null },
          { name: "moveTo", arguments: [{ position: { x: 0, y: 0 } }] },
          { name: "focus", arguments: [1] },
          { name: "releaseNode", arguments: null },
          { name: "getOptionsFromConfigurator", arguments: null },
        ];

        drawQuick();
        for (var i = 0; i < methods.length; i++) {
          setTimeout(testMethod.bind(this, methods, i), i * 50);
        }
      }

      function testMethod(methods, i) {
        var methodName = methods[i].name;
        console.log("Currently testing:", methodName);

        if (methods[i].funcFirst !== undefined) {
          methods[i].funcFirst();
        }

        if (methods[i].func !== undefined) {
          methods[i].func();
        } else {
          if (methods[i].arguments === null) {
            network[methodName].apply(network);
          } else {
            network[methodName].apply(network, methods[i].arguments);
          }
        }
      }

      var amountOfOptionChecks = 50;
      var optionsThreshold = 0.8;
      var optionGlobalCount = 0;
      function checkOptions() {
        optionGlobalCount++;
        if (optionGlobalCount == amountOfOptionChecks) {
          checkMethods();
        } else {
          var allOptions = vis.network.allOptions.allOptions;
          var testOptions = {};
          constructOptions(allOptions, testOptions);
          if (testOptions.physics === undefined) {
            testOptions.physics = {};
          }
          if (testOptions.layout === undefined) {
            testOptions.layout = {};
          }
          testOptions.physics.enabled = true;
          testOptions.layout.improvedLayout = false;
          var failed = setTimeout(function () {
            console.error("FAILED", JSON.stringify(testOptions, null, 4));
          }, 500);
          var counter = 0;
          drawQuick();
          network.on("afterDrawing", function () {
            counter++;
            if (counter > 2) {
              counter = 0;
              network.off("afterDrawing");
              clearTimeout(failed);
              network.destroy();
            }
          });
          network.on("stabilized", function () {
            clearTimeout(failed);
            network.destroy();
          });
          network.once("destroy", function () {
            clearTimeout(failed);
            setTimeout(checkOptions, 100);
          });
          console.log("now testing:", testOptions);

          network.setOptions(testOptions);
        }
      }

      function constructOptions(allOptions, testOptions) {
        for (var option in allOptions) {
          if (Math.random() < optionsThreshold) {
            if (
              option !== "__type__" &&
              option !== "__any__" &&
              option !== "locales" &&
              option !== "image" &&
              option !== "id"
            ) {
              if (allOptions[option].__type__ !== undefined) {
                if (testOptions[option] === undefined) {
                  testOptions[option] = {};
                }
                constructOptions(allOptions[option], testOptions[option]);
                if (Object.keys(testOptions).length === 0) {
                  testOptions[option] = undefined;
                  delete testOptions[option];
                }
              } else {
                if (allOptions[option].boolean !== undefined) {
                  if (testOptions[option] === undefined) {
                    testOptions[option] = {};
                  }
                  testOptions[option] = Math.random() < 0.5;
                } else if (allOptions[option].number !== undefined) {
                  if (testOptions[option] === undefined) {
                    testOptions[option] = {};
                  }
                  testOptions[option] = 1 * Math.random();
                } else if (
                  allOptions[option].string !== undefined &&
                  Array.isArray(allOptions[option].string)
                ) {
                  var value =
                    allOptions[option].string[
                      Math.floor(
                        Math.random() * allOptions[option].string.length
                      )
                    ];
                  if (
                    value !== "image" &&
                    value !== "circularImage" &&
                    value !== "icon"
                  ) {
                    if (testOptions[option] === undefined) {
                      testOptions[option] = {};
                    }
                    testOptions[option] = value;
                  }
                } else if (allOptions[option].string !== undefined) {
                  //                            if (testOptions[option] === undefined) {
                  //                                testOptions[option] = {};
                  //                            }
                  //                            testOptions[option] = "hello world";
                }
              }
            }
          }
        }
      }

      checkOptions();
      //    for (var i = 0; i < amountOfOptionChecks; i++) {
      //        setTimeout(checkOptions.bind(this,i), i*optionCheckTime);
      //    }
      //    setTimeout(checkMethods, amountOfOptionChecks*optionCheckTime);
    </script>
  </body>
</html>
